<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  

  
  <title>Android——MQTT推送 | 海晨忆的博客</title>
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
  
  
  
  <meta name="description" content="整体介绍&amp;emsp;&amp;emsp;最近公司用到的推送MQTT。不想过多的介绍背景什么的，我就直接讲怎么实现这个功能。 &amp;emsp;&amp;emsp;他这个原理长连接，这个不用多讲，用法类似于EventBus，需要先订阅，然后通过topic再发送消息。topic是什么呢？我先来讲讲整体流程：">
<meta property="og:type" content="article">
<meta property="og:title" content="Android——MQTT推送">
<meta property="og:url" content="https://haichenyi.com/2018/05/13/Android——MQTT推送/index.html">
<meta property="og:site_name" content="海晨忆的博客">
<meta property="og:description" content="整体介绍&amp;emsp;&amp;emsp;最近公司用到的推送MQTT。不想过多的介绍背景什么的，我就直接讲怎么实现这个功能。 &amp;emsp;&amp;emsp;他这个原理长连接，这个不用多讲，用法类似于EventBus，需要先订阅，然后通过topic再发送消息。topic是什么呢？我先来讲讲整体流程：">
<meta property="og:locale" content="zh-Hans">
<meta property="og:updated_time" content="2018-05-13T14:36:43.726Z">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="Android——MQTT推送">
<meta name="twitter:description" content="整体介绍&amp;emsp;&amp;emsp;最近公司用到的推送MQTT。不想过多的介绍背景什么的，我就直接讲怎么实现这个功能。 &amp;emsp;&amp;emsp;他这个原理长连接，这个不用多讲，用法类似于EventBus，需要先订阅，然后通过topic再发送消息。topic是什么呢？我先来讲讲整体流程：">
  
    <link rel="alternate" href="/atom.xml" title="海晨忆的博客" type="application/atom+xml">
  
  
    <link rel="icon" href="/uploads/artistic_image/head.jpg">
  
  
    <link href="//fonts.googleapis.com/css?family=Source+Code+Pro" rel="stylesheet" type="text/css">
  
  <link rel="stylesheet" href="/css/style.css">
  <link rel="stylesheet" href="/css/highlight.css">
  <script>
  let antiquityStorage = window.sessionStorage.getItem('antiquitySessionStorage');
  if (antiquityStorage == '' || antiquityStorage == null) {
    var antiquityLoader = '<div id="loaderbox"><div class="loader"><div class="load-roll"><div class="load-top"></div><div class="load-right"></div><div class="load-bottom"></div></div></div></div>';
    document.write(antiquityLoader);
    document.body.style.overflow = 'hidden'
  }
  </script>
</head>

<body>
  <div id="fullpage" class="mobile-nav-right">
    
      <div id="wrapper" style="background-image: url(/uploads/artistic_image/bg.jpg)" title="背景图片来自网络">
    
    
      <header id="header">
  <div id="nav-toggle" class="nav-toggle"></div>
  <div class="head-box global-width">
    <nav class="nav-box nav-right">
      
        <a class="nav-item" href="/" title
        
        >首页</a>
      
        <a class="nav-item" href="/archives" title
        
        >归档</a>
      
        <a class="nav-item" href="/about" title
        
        >简历</a>
      
    </nav>
  </div>
</header>
      <div id="middlecontent" title class="global-width sidebar-left">
        <section id="main"><article id="post-Android——MQTT推送" class="article global-container article-type-post" itemscope itemprop="blogPost">
  
    <header class="article-header">
      
  
    <h1 class="article-title" itemprop="name">
      Android——MQTT推送
    </h1>
  

    </header>
  
  <div class="article-meta">
    <a href="/2018/05/13/Android——MQTT推送/" class="article-date">
  <time datetime="2018-05-13T14:28:22.000Z" itemprop="datePublished">2018-05-13</time>
</a>
    
  <div class="article-category">
    <a class="article-category-link" href="/categories/Android-常用功能/">Android -常用功能</a>
  </div>

    
  </div>
  
    <span id="busuanzi_container_page_pv">
      本文总阅读量<span id="busuanzi_value_page_pv"></span>次
    </span>
  

  <div class="article-inner">
    
    <div class="article-content article-content-cloud doorframe mac" itemprop="articleBody">
      
        <h3 id="整体介绍"><a href="#整体介绍" class="headerlink" title="整体介绍"></a>整体介绍</h3><p>&emsp;&emsp;最近公司用到的推送MQTT。不想过多的介绍背景什么的，我就直接讲怎么实现这个功能。</p>
<p>&emsp;&emsp;他这个原理长连接，这个不用多讲，用法类似于EventBus，需要先订阅，然后通过topic再发送消息。topic是什么呢？我先来讲讲整体流程：</p>
 <a id="more"></a>
<ol>
<li><p>先连接服务器，要先建立长连接</p>
</li>
<li><p>然后需要订阅topic，连接之后才能订阅topic</p>
</li>
<li><p>最后就是通过topic推送消息，接收消息</p>
</li>
</ol>
<p>一步一步讲：</p>
<h3 id="第一步，与服务器建立连接"><a href="#第一步，与服务器建立连接" class="headerlink" title="第一步，与服务器建立连接"></a>第一步，与服务器建立连接</h3><p>&emsp;&emsp;先丢代码，然后看注释：</p>
<div class="highlight-box"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="PLAIN"><figure class="iseeu highlight /plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line">private void initPush() &#123;</span><br><span class="line">        // 服务器地址（协议+地址+端口号）</span><br><span class="line">        String uri = host;</span><br><span class="line">        client = new MqttAndroidClient(this, uri, clientId);</span><br><span class="line">        // 设置MQTT监听并且接受消息</span><br><span class="line">        client.setCallback(mqttCallback);</span><br><span class="line">        //Mqtt的一些设置</span><br><span class="line">        conOpt = new MqttConnectOptions();</span><br><span class="line">        conOpt.setAutomaticReconnect(true);</span><br><span class="line">        // 清除缓存</span><br><span class="line">        conOpt.setCleanSession(true);</span><br><span class="line">        // 设置超时时间，单位：秒</span><br><span class="line">        conOpt.setConnectionTimeout(10);</span><br><span class="line">        // 心跳包发送间隔，单位：秒</span><br><span class="line">        conOpt.setKeepAliveInterval(20);</span><br><span class="line">        myTopic = String.format(TOPIC_SUB, mDeviceId);</span><br><span class="line">        Log.e(TAG,&quot;myTopic_________&quot;+myTopic);</span><br><span class="line">        doClientConnection();</span><br><span class="line">    &#125;</span><br></pre></td></tr></table></figure></div>
<p>&emsp;&emsp;上面的这些参数，我碰到了两个问题。</p>
<p>&emsp;&emsp;上面的这些参数，我碰到了两个问题。</p>
<p>&emsp;&emsp;上面的这些参数，我碰到了两个问题。</p>
<ol>
<li>第一个问题，与服务器建立连接，你得先有一个服务器吧？我根据网上的步骤，创建了一个apache-apollo服务器，并且启动了，也启动成功了，我建立连接的时候，总是失败。然后，找啊找，找啊找。问题没有解决，但是，我找到了一个可以用的服务器，也就是这里的uri，不要设置MqttConnectOptions的用户名和密码，设置了他会拒绝</li>
</ol>
<div class="highlight-box"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="PLAIN"><figure class="iseeu highlight /plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">private String host = &quot;tcp://test.mosquitto.org:1883&quot;;</span><br></pre></td></tr></table></figure></div>
<ol>
<li>第二个问题，我连接成功之后，不一会，他就会自动断开连接，或者，推送完消息之后，他就会断开连接。然后，网上搜原因，找啊找，诶，我找到了。MqttAndroidClient的构造方法：</li>
</ol>
<div class="highlight-box"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="PLAIN"><figure class="iseeu highlight /plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line">/**</span><br><span class="line">	 * Constructor - create an MqttAndroidClient that can be used to communicate with an MQTT server on android</span><br><span class="line">	 * </span><br><span class="line">	 * @param context </span><br><span class="line">	 *            object used to pass context to the callback. </span><br><span class="line">	 * @param serverURI</span><br><span class="line">	 *            specifies the protocol, host name and port to be used to</span><br><span class="line">	 *            connect to an MQTT server</span><br><span class="line">	 * @param clientId</span><br><span class="line">	 *            specifies the name by which this connection should be</span><br><span class="line">	 *            identified to the server</span><br><span class="line">	 */</span><br><span class="line">	public MqttAndroidClient(Context context, String serverURI,</span><br><span class="line">			String clientId) &#123;</span><br><span class="line">		this(context, serverURI, clientId, null, Ack.AUTO_ACK);</span><br><span class="line">	&#125;</span><br></pre></td></tr></table></figure></div>
<p>看第三个参数，clientId，指定一个名字，用来连接服务器的身份标识。就是说，你设置的这个值，是你在服务器的唯一标识，不能跟其他用户的相同。我把这个clientId直接用uuid生成，就没问题了。</p>
<h3 id="第二步，订阅topic"><a href="#第二步，订阅topic" class="headerlink" title="第二步，订阅topic"></a>第二步，订阅topic</h3><p>&emsp;&emsp;回到上面，接着往下面走，</p>
<div class="highlight-box"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="PLAIN"><figure class="iseeu highlight /plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br></pre></td><td class="code"><pre><span class="line">/**</span><br><span class="line">     * 连接MQTT服务器</span><br><span class="line">     */</span><br><span class="line">    private void doClientConnection() &#123;</span><br><span class="line">        if (!client.isConnected() &amp;&amp; isConnectIsNormal()) &#123;</span><br><span class="line">            try &#123;</span><br><span class="line">                client.connect(conOpt, null, iMqttActionListener);</span><br><span class="line">            &#125; catch (MqttException e) &#123;</span><br><span class="line">                e.printStackTrace();</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    /**</span><br><span class="line">     * 判断网络是否连接</span><br><span class="line">     */</span><br><span class="line">    private boolean isConnectIsNormal() &#123;</span><br><span class="line">        ConnectivityManager connectivityManager = (ConnectivityManager) this.getApplicationContext()</span><br><span class="line">                .getSystemService(Context.CONNECTIVITY_SERVICE);</span><br><span class="line">        if (connectivityManager != null) &#123;</span><br><span class="line">            NetworkInfo info = connectivityManager.getActiveNetworkInfo();</span><br><span class="line">            if (info != null &amp;&amp; info.isAvailable()) &#123;</span><br><span class="line">                String name = info.getTypeName();</span><br><span class="line">                Log.e(TAG, &quot;MQTT当前网络名称：&quot; + name);</span><br><span class="line">                return true;</span><br><span class="line">            &#125; else &#123;</span><br><span class="line">                Log.e(TAG, &quot;MQTT 没有可用网络&quot;);</span><br><span class="line">                return false;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125; else &#123;</span><br><span class="line">            return false;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br></pre></td></tr></table></figure></div>
<p>&emsp;&emsp;这个方法就是用来连接服务器的，首先判断是否正在连接，后面那个是判断当前有没有网络。再就是这个iMqttActionListener监听了</p>
<div class="highlight-box"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="PLAIN"><figure class="iseeu highlight /plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line">// MQTT是否连接成功</span><br><span class="line">    private IMqttActionListener iMqttActionListener = new IMqttActionListener() &#123;</span><br><span class="line"></span><br><span class="line">        @Override</span><br><span class="line">        public void onSuccess(IMqttToken arg0) &#123;</span><br><span class="line">            Log.e(TAG, &quot;连接成功 &quot;);</span><br><span class="line">            try &#123;</span><br><span class="line">                // 订阅myTopic话题</span><br><span class="line">                client.subscribe(myTopic, 0);</span><br><span class="line">            &#125; catch (MqttException e) &#123;</span><br><span class="line">                e.printStackTrace();</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        @Override</span><br><span class="line">        public void onFailure(IMqttToken arg0, Throwable arg1) &#123;</span><br><span class="line">            Log.e(TAG, &quot;连接失败&quot;);</span><br><span class="line">            arg1.printStackTrace();</span><br><span class="line">            // 连接失败，重连</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;;</span><br></pre></td></tr></table></figure></div>
<p>&emsp;&emsp;讷，就是这里，你如果服务器有问题，他一直走onFailure方法。服务器连接成功之后，就是订阅topic。我来说说这个</p>
<div class="highlight-box"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="PLAIN"><figure class="iseeu highlight /plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">client.subscribe(myTopic, 0);</span><br></pre></td></tr></table></figure></div>
<p>&emsp;&emsp;首先，这个主题，是你自己跟服务器商量好的，随便什么都可以。为什么要订阅主题呢？我提前给你瞅瞅推送消息是怎么推送的</p>
<p>&emsp;&emsp;第二个参数，消息的类型qos，有三种：0、1、2</p>
<ol>
<li>0代表“至多一次”，消息发布完全依赖底层 TCP/IP 协议。会发生消息丢失或重复。这一级别可用于如下情况，环境传感器数据，丢失一次读记录无所谓，因为不久后还会有第二次发送</li>
<li>1代表“至少一次”，确保消息到达，但消息重复可能会发生</li>
<li>2代表“只有一次”，确保消息到达一次。这一级别可用于如下情况，在计费系统中，消息重复或丢失会导致不正确的结果。</li>
</ol>
<p>&emsp;&emsp;简单说明下，如果发送的是临时的消息，例如给某topic所有在线的设备发送一条消息，丢失的话也无所谓，0就可以了。如果需要客户端保证能接收消息，需要指定QoS为1</p>
<div class="highlight-box"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="PLAIN"><figure class="iseeu highlight /plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">client.publish(topic, new MqttMessage(msg.getBytes()));</span><br></pre></td></tr></table></figure></div>
<p>&emsp;&emsp;讷，推送消息，是根据topic推送的，第二个参数，就是你要推送的具体消息。我个人认为，你可以理解成就类似于键值对的形式，</p>
<p><strong><em>不同的用户可以订阅相同的主题</em></strong></p>
<p><strong><em>不同的用户可以订阅相同的主题</em></strong></p>
<p><strong><em>不同的用户可以订阅相同的主题</em></strong></p>
<p>&emsp;&emsp;这个就是跟其他长连接不同的地方，底层，其实都一样，虽然我没有看底层的代码。想也想的到，服务器肯定是根据这个主题，去找对应的用户，然后推送消息。而其他的长连接就是直接指定用户。跑题了，跑题了。</p>
<h3 id="第三步，推送、接收消息"><a href="#第三步，推送、接收消息" class="headerlink" title="第三步，推送、接收消息"></a>第三步，推送、接收消息</h3><p>&emsp;&emsp;当你连接服务器成功之后，就要推送消息了，我用的EventBus发的</p>
<div class="highlight-box"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="PLAIN"><figure class="iseeu highlight /plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line">private void publishData(String msg) &#123;</span><br><span class="line">        String topic = myTopic;</span><br><span class="line">        try &#123;</span><br><span class="line">            Log.e(TAG,&quot;给__&quot;+topic+&quot;__topic发送的消息为：&quot;+msg);</span><br><span class="line">            client.publish(topic, new MqttMessage(msg.getBytes()));</span><br><span class="line">        &#125; catch (MqttException e) &#123;</span><br><span class="line">            e.printStackTrace();</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    // MQTT监听并且接受消息</span><br><span class="line">    private MqttCallback mqttCallback = new MqttCallback() &#123;</span><br><span class="line"></span><br><span class="line">        @Override</span><br><span class="line">        public void messageArrived(String topic, MqttMessage message) throws Exception &#123;</span><br><span class="line">            Log.e(TAG,&quot;接受到__&quot;+topic+&quot;__topic的消息为：&quot;+new String(message.getPayload()));</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        @Override</span><br><span class="line">        public void deliveryComplete(IMqttDeliveryToken arg0) &#123;</span><br><span class="line">            Log.e(TAG,&quot;deliveryComplete&quot;);</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        @Override</span><br><span class="line">        public void connectionLost(Throwable arg0) &#123;</span><br><span class="line">            // 失去连接，重连</span><br><span class="line">            Log.e(TAG,&quot;失去连接&quot;);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;;</span><br></pre></td></tr></table></figure></div>
<p>&emsp;&emsp;当你的clientId重复的时候，他就会一直走connectionLost方法。到这里，基本上就讲完了，要注意的是，退出的时候，记得要释放资源</p>
<div class="highlight-box"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="PLAIN"><figure class="iseeu highlight /plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">@Override</span><br><span class="line">    public void onDestroy() &#123;</span><br><span class="line">        try &#123;</span><br><span class="line">            if (client != null &amp;&amp; client.isConnected()) &#123;</span><br><span class="line">                client.disconnect();</span><br><span class="line">            &#125;</span><br><span class="line">        &#125; catch (MqttException e) &#123;</span><br><span class="line">            e.printStackTrace();</span><br><span class="line">        &#125;</span><br><span class="line">        EventBus.getDefault().unregister(this);</span><br><span class="line">        super.onDestroy();</span><br><span class="line">    &#125;</span><br></pre></td></tr></table></figure></div>
<p>网上很多都是直接讲整体流程，重来不讲中间碰到的问题。难受</p>
<p><a href="https://download.csdn.net/download/qq_27634797/10408420" target="_blank" rel="noopener">项目链接</a></p>

      
    </div>
    
      <footer class="article-footer">
        完
      </footer>
    
  </div>
  
    
<nav id="article-nav">
  <div class="article-nav-block">
    
      <a href="/2018/10/11/MySQL数据库操作（一）——DDL、DML、DCL/" id="article-nav-newer" class="article-nav-link-wrap">
        <strong class="article-nav-caption"></strong>
        <div class="article-nav-title">
          
            MySQL数据库操作（一）——DDL、DML、DCL
          
        </div>
      </a>
    
  </div>
  <div class="article-nav-block">
    
      <a href="/2018/05/13/Android—React-Native编程/" id="article-nav-older" class="article-nav-link-wrap">
        <div class="article-nav-title">Android—React Native编程</div>
        <strong class="article-nav-caption"></strong>
      </a>
    
  </div>
</nav>

    
  
  
</article>
</section>
        <aside id="sidebar">
  
    <div class="widget-box">
  <div class="avatar-box avatar-item">
    <img class="avatar" src="/uploads/artistic_image/head.jpg" title="头像来自网络"></img>
    <h3 class="avatar-name">
      
        海晨忆
      
    </h3>
    <p class="avatar-slogan">
      先谋生，再谋爱。人间值得，未来可期。
    </p>
  </div>
</div>


  
    
  <div class="widget-box">
    <h3 class="widget-title">分类</h3>
    <div class="widget">
      <ul class="category-list"><li class="category-list-item"><a class="category-list-link" href="/categories/Android-Socket/">Android -Socket</a></li><li class="category-list-item"><a class="category-list-link" href="/categories/Android-加密算法/">Android -加密算法</a></li><li class="category-list-item"><a class="category-list-link" href="/categories/Android-常用功能/">Android -常用功能</a></li><li class="category-list-item"><a class="category-list-link" href="/categories/Android-框架/">Android -框架</a></li><li class="category-list-item"><a class="category-list-link" href="/categories/Android-源码解析/">Android -源码解析</a></li><li class="category-list-item"><a class="category-list-link" href="/categories/Android-自定义view/">Android -自定义view</a></li><li class="category-list-item"><a class="category-list-link" href="/categories/Android-设计模式/">Android -设计模式</a></li><li class="category-list-item"><a class="category-list-link" href="/categories/JAVA-并发/">JAVA -并发</a></li><li class="category-list-item"><a class="category-list-link" href="/categories/Java-SpringBoot/">Java -SpringBoot</a></li><li class="category-list-item"><a class="category-list-link" href="/categories/Tomcat/">Tomcat</a></li><li class="category-list-item"><a class="category-list-link" href="/categories/kotlin/">kotlin</a></li><li class="category-list-item"><a class="category-list-link" href="/categories/数据库-JDBC/">数据库 -JDBC</a></li><li class="category-list-item"><a class="category-list-link" href="/categories/数据库-MySQL/">数据库 -MySQL</a></li></ul>
    </div>
  </div>


  
    

  
    
  
    
  <div class="widget-box">
    <h3 class="widget-title">归档</h3>
    <div class="widget">
      <ul class="archive-list"><li class="archive-list-item"><a class="archive-list-link" href="/archives/2021/07/">July 2021</a></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2019/11/">November 2019</a></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2019/10/">October 2019</a></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2019/09/">September 2019</a></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2019/08/">August 2019</a></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2019/07/">July 2019</a></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2019/06/">June 2019</a></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2018/10/">October 2018</a></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2018/05/">May 2018</a></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2018/03/">March 2018</a></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2018/02/">February 2018</a></li></ul>
    </div>
  </div>

  
    
  <div class="widget-box">
    <h3 class="widget-title">最新文章</h3>
    <div class="widget">
      <ul>
        
          <li>
            <a href="/2021/07/27/JAVA—公平锁，非公平锁，悲观锁，乐观锁，死锁/">JAVA—公平锁，非公平锁，悲观锁，乐观锁，死锁</a>
          </li>
        
          <li>
            <a href="/2021/07/19/JAVA—线程同步器AQS/">JAVA—线程同步器AQS</a>
          </li>
        
          <li>
            <a href="/2021/07/07/Android模拟点击/">Android模拟点击</a>
          </li>
        
          <li>
            <a href="/2019/11/27/SpringBoot系列-消息-RabbitMQ-（二十）/">SpringBoot系列-消息(RabbitMQ)（二十）</a>
          </li>
        
          <li>
            <a href="/2019/11/13/SpringBoot系列-Docker（十九）/">SpringBoot系列-Docker（十九）</a>
          </li>
        
      </ul>
    </div>
  </div>

  
      <div class="widget-box">
    <h3 class="widget-title">友情链接</h3>
    <div class="widget">
      
        <a class="hrf" style="display: block;" href="https://github.com/haichenyi" title target='_blank'
        >Github</a>
      
        <a class="hrf" style="display: block;" href="https://www.jianshu.com/u/6077ee440c37" title target='_blank'
        >简书</a>
      
        <a class="hrf" style="display: block;" href="https://blog.csdn.net/qq_27634797" title target='_blank'
        >CSDN</a>
      
    </div>
  </div>

  
</aside>
      </div>
      <footer id="footer">
  <div class="foot-box footers global-width">
    &copy;2017-2021 海晨忆 &nbsp;&nbsp;
    <script async src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script>
    <span id="busuanzi_container_site_pv">阁下是第<span id="busuanzi_value_site_pv"></span>个访客</span>
  </div>
</footer>
      <script src="https://code.jquery.com/jquery-2.0.3.min.js"></script>
<script>
if (!window.jQuery) {
var script = document.createElement('script');
script.src = "/js/jquery-2.0.3.min.js";
document.body.write(script);
}
</script>

  <link rel="stylesheet" href="/fancybox/jquery.fancybox.css">
  <script src="/fancybox/jquery.fancybox.pack.js"></script>


<script src="/js/script.js"></script>



    </div>
    <nav id="mobile-nav" class="mobile-nav-box">
  <div class="mobile-nav-img mobile-nav-top"></div>
  
    <a href="/" class="mobile-nav-link">首页</a>
  
    <a href="/archives" class="mobile-nav-link">归档</a>
  
    <a href="/about" class="mobile-nav-link">简历</a>
  
  <div class="mobile-nav-img  mobile-nav-bottom"></div>
</nav>    
  </div>
</body>
</html>